home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 41.zip / BS1 part 41 / Compute`s Amiga resource 1.adf / Source / ALC / advsound.c < prev    next >
C/C++ Source or Header  |  1989-02-07  |  16KB  |  638 lines

  1. /* Advanced Laser Chess sound routines */
  2.  
  3. #include "advlaser.h"
  4. #include "advsound.h"
  5. #include <devices/audio.h>
  6. #include <stdio.h>
  7.  
  8. /* Externals */
  9. extern UWORD clup;  /* ADVDOOR.C */
  10. extern int turn;    /* ADVLASER.C */
  11. extern void *allocate_mem(); /* ADVLASER.C */
  12.  
  13. /* Local variables */
  14. struct IOAudio *ioaudio;         /* Main ioaudio structure */
  15. struct Unit *unit[4];            /* Individual channel units */
  16. WORD allockey[4];                /* Individual channel allocation keys */
  17. BOOL in_use[4];                  /* Keeps track of which channels in use */
  18. struct MsgPort *static_port, *dynamic_port;
  19. UBYTE *load_raw_sample();
  20. UBYTE *waveform[NUMSAMPLES];
  21. ULONG wavelength[NUMSAMPLES];
  22. int general_channel = -1;
  23. int background_on = FALSE, background_channel = -1, background_period;
  24. int victory_period, victory_volume = 0;
  25. int title_period, title_volume = 0;
  26.  
  27.  
  28.  
  29.  
  30. init_sound()
  31. {
  32.   register int i;
  33.  
  34.   if((ioaudio = allocate_mem((long)sizeof(struct IOAudio),
  35.   MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  36.     cleanup(NOMEM);
  37.   if((static_port = CreatePort(NULL, NULL)) == NULL)
  38.     cleanup(NOAUDIOREPLYPORT);
  39.   if((dynamic_port = CreatePort(NULL, NULL)) == NULL)
  40.     cleanup(NOAUDIOREPLYPORT);
  41.   ioaudio->ioa_Request.io_Message.mn_ReplyPort = static_port;
  42.   if((OpenDevice("audio.device", NULL, ioaudio, NULL)) != NULL)
  43.     cleanup(NOAUDIODEVICE);
  44.   clup |= CLUP_AUDIODEV;
  45.  
  46.   for(i=0; i<4; i++)
  47.   {
  48.     allockey[i] = 0;
  49.     unit[i] = NULL;
  50.     in_use[i] = FALSE;
  51.   }
  52.   general_channel = allocate_audio_channel(GENERAL_CHANNEL_PRIORITY);
  53.   load_waveforms();
  54. }
  55.  
  56.  
  57.  
  58. beep()
  59. {
  60.   static int b = 0;
  61.   register int i, at_least_one = FALSE;
  62.  
  63.   for(i=0; i<NUMBEEPS; i++)  /* See if any "beep" waveforms exist */
  64.     if(waveform[i] != NULL)
  65.       at_least_one = TRUE;
  66.   if(!at_least_one) return; /* Return; no beeps are present to be played */
  67.  
  68.   /* Make sure that existing waveforms are played, as opposed to letting
  69.   missing "beep" waveforms be played (as silence) */
  70.   do
  71.   {
  72.     if(waveform[b] == NULL) ++b;
  73.     if(b >= NUMBEEPS) b = 0;
  74.   } while(waveform[b] == NULL);
  75.  
  76.   end_sound(general_channel, !NOW);
  77.   switch(b)
  78.   {
  79.     case 0:
  80.       start_sound(general_channel, waveform[WAVE_BEEP0],
  81.         wavelength[WAVE_BEEP0], BEEP0_PERIOD, BEEP0_VOLUME, BEEP0_CYCLES);
  82.       break;
  83.  
  84.     case 1:
  85.       start_sound(general_channel, waveform[WAVE_BEEP1],
  86.         wavelength[WAVE_BEEP1], BEEP1_PERIOD, BEEP1_VOLUME, BEEP1_CYCLES);
  87.       break;
  88.   }
  89.   if(++b >= NUMBEEPS) b = 0;
  90. }
  91.  
  92.  
  93.  
  94. disk_open_sound()
  95. {
  96.   end_sound(general_channel, NOW);
  97.   start_sound(general_channel, waveform[WAVE_DISKOPEN],
  98.     wavelength[WAVE_DISKOPEN], DISKOPEN_PERIOD, DISKOPEN_VOLUME,
  99.     DISKOPEN_CYCLES);
  100. }
  101.  
  102.  
  103.  
  104. disk_close_sound()
  105. {
  106.   end_sound(general_channel, NOW);
  107.   start_sound(general_channel, waveform[WAVE_DISKCLOSE],
  108.     wavelength[WAVE_DISKCLOSE], DISKCLOSE_PERIOD, DISKCLOSE_VOLUME,
  109.     DISKCLOSE_CYCLES);
  110. }
  111.  
  112.  
  113.  
  114. laser_sound(player)
  115. register int player;
  116. {
  117.   register int p;
  118.  
  119.   p = player == RED? 0 : 200;
  120.   laser_sound_off();
  121.   start_sound(general_channel, waveform[WAVE_LASER], wavelength[WAVE_LASER],
  122.     LASER_PERIOD + p, LASER_VOLUME, LASER_CYCLES);
  123. }
  124.  
  125.  
  126.  
  127. laser_sound_off()
  128. {
  129.   end_sound(general_channel, NOW);
  130. }
  131.  
  132.  
  133.  
  134. hyper_in_sound()
  135. {
  136.   end_sound(general_channel, NOW);
  137.   start_sound(general_channel, waveform[WAVE_HYPERIN],
  138.     wavelength[WAVE_HYPERIN], HYPERIN_PERIOD + rnd(150), HYPERIN_VOLUME,
  139.     HYPERIN_CYCLES);
  140. }
  141.  
  142.  
  143.  
  144. hyper_out_sound()
  145. {
  146.   end_sound(general_channel, NOW);
  147.   start_sound(general_channel, waveform[WAVE_HYPEROUT],
  148.     wavelength[WAVE_HYPEROUT], HYPEROUT_PERIOD + rnd(100), HYPEROUT_VOLUME,
  149.     HYPEROUT_CYCLES);
  150. }
  151.  
  152.  
  153.  
  154. crunch_sound()
  155. {
  156.   end_sound(general_channel, NOW);
  157.   start_sound(general_channel, waveform[WAVE_CRUNCH],
  158.     wavelength[WAVE_CRUNCH], CRUNCH_PERIOD, CRUNCH_VOLUME,
  159.     CRUNCH_CYCLES);
  160. }
  161.  
  162.  
  163.  
  164. explode_sound()
  165. {
  166.   end_sound(general_channel, NOW);
  167.   start_sound(general_channel, waveform[WAVE_EXPLODE],
  168.     wavelength[WAVE_EXPLODE], EXPLODE_PERIOD, EXPLODE_VOLUME, EXPLODE_CYCLES);
  169. }
  170.  
  171.  
  172.  
  173. background_sound(on_off, volume)
  174. register int on_off, volume;   /* TRUE=on, FALSE=off, TOGGLE=switch on/off */
  175. {
  176.   if(turn == RED) background_period = BACKGROUND_PERIOD;
  177.   else background_period = BACKGROUND_PERIOD + 8;
  178.  
  179.   if(on_off == TOGGLE)
  180.     background_on = !background_on;
  181.  
  182.   if(on_off == TRUE || (on_off == TOGGLE && background_on == TRUE))
  183.   {
  184.     if(background_channel == -1)
  185.       background_channel = allocate_audio_channel(BACKGROUND_PRIORITY);
  186.     start_sound(background_channel, waveform[WAVE_BACKGROUND],
  187.       wavelength[WAVE_BACKGROUND], background_period, volume,
  188.       BACKGROUND_CYCLES);
  189.     background_on = TRUE;
  190.   }
  191.   else if(on_off == FALSE || (on_off == TOGGLE && background_on == FALSE))
  192.   {
  193.     end_sound(background_channel, NOW);
  194.     free_audio_channel(background_channel);
  195.     background_channel = -1;
  196.     background_on = FALSE;
  197.   }
  198. }
  199.  
  200.  
  201.  
  202. modify_background_sound()  /* Called from fade() (ADVGRAPH.C) */
  203. {
  204.   background_period += turn == RED? -1 : 1;
  205.   if(background_period < BACKGROUND_PERIOD)
  206.     background_period = BACKGROUND_PERIOD;
  207.   else if(background_period > BACKGROUND_PERIOD + 8)
  208.     background_period = BACKGROUND_PERIOD + 8;
  209.  
  210.   modify_sound(background_channel, background_period, BACKGROUND_VOLUME);
  211. }
  212.  
  213.  
  214.  
  215. victory_chord(on_off)  /* TRUE = on, FALSE = off */
  216. register int on_off;
  217. {
  218.   static int back;
  219.  
  220.   end_sound(general_channel, NOW);
  221.   if(on_off == TRUE)
  222.   {
  223.     back = background_on;
  224.     if(background_on) background_sound(FALSE, 0);
  225.     /* Start victory chord at volume zero */
  226.     victory_volume = 0;
  227.     victory_period = VICTORY_PERIOD;
  228.     start_sound(general_channel, waveform[WAVE_VICTORY],
  229.       wavelength[WAVE_VICTORY], VICTORY_PERIOD, 0,
  230.       VICTORY_CYCLES);
  231.   }
  232.   else  /* If turning off sound, reset victory sound parameters */
  233.   {
  234.     end_sound(general_channel, NOW);
  235.     victory_period = VICTORY_PERIOD;
  236.     victory_volume = 0;
  237.     if(back) background_sound(TRUE, BACKGROUND_VOLUME);
  238.   }
  239. }
  240.  
  241.  
  242.  
  243. modify_victory_sound(up_down)  /* up_down = 1 for up, -1 for down. */
  244. register int up_down;
  245. {
  246.   victory_period -= 5 * up_down;
  247.   victory_volume += 2 * up_down;
  248.  
  249.   modify_sound(general_channel, victory_period, victory_volume);
  250. }
  251.  
  252.  
  253.  
  254. title_sound(on_off)  /* TRUE=on, FALSE=off */
  255. {
  256.   static int back;
  257.  
  258.   if(on_off == TRUE)
  259.   {
  260.     back = background_on;
  261.     if(background_on) background_sound(FALSE, 0);
  262.  
  263.     background_channel = allocate_audio_channel(BACKGROUND_PRIORITY);
  264.  
  265.     /* Start title chords at zero volume */
  266.     title_volume = 0;
  267.     title_period = TITLE_PERIOD;
  268.     start_sound(general_channel, waveform[WAVE_TITLE],
  269.       wavelength[WAVE_TITLE], TITLE_PERIOD, 0, TITLE_CYCLES);
  270.     start_sound(background_channel, waveform[WAVE_TITLE],
  271.       wavelength[WAVE_TITLE], TITLE_PERIOD, 0, TITLE_CYCLES);
  272.   }
  273.   else  /* If turning off sound, reset title sound parameters */
  274.   {
  275.     end_sound(general_channel, NOW);
  276.     end_sound(background_channel, NOW);
  277.     title_period = TITLE_PERIOD;
  278.     title_volume = 0;
  279.     if(back)
  280.       background_sound(TRUE, 0);
  281.   }
  282. }
  283.  
  284.  
  285.  
  286. modify_title_sound(up_down)  /* up_down = 1 for up, -1 for down. */
  287. register int up_down;
  288. {
  289.   title_volume += 1 * up_down;
  290.   title_period -= 1 * up_down;
  291.   if(title_volume < 0) title_volume = 0;
  292.  
  293.   modify_sound(general_channel, title_period,
  294.     title_volume > TITLE_MAX_VOLUME? TITLE_MAX_VOLUME : title_volume);
  295.   modify_sound(background_channel, title_period,
  296.     title_volume > TITLE_MAX_VOLUME? TITLE_MAX_VOLUME : title_volume);
  297. }
  298.  
  299.  
  300.  
  301. rnd_title_chord(first)  /* Changes the title chord */
  302. register int first;
  303. {
  304.   static int period1[] = {306, 274, 306, 229, 306, 171, 388, 171, 306};
  305.   static int period2[] = {306, 306, 256, 306, 204, 345, 153, 345, 153};
  306.   static int count = 0, note_count = 0;
  307.  
  308.   if(first)
  309.     note_count = 0;
  310.  
  311.   if(++count < 12000)
  312.     return;
  313.   count = 0;
  314.  
  315.   modify_sound(general_channel, period1[note_count],
  316.     title_volume > TITLE_MAX_VOLUME? TITLE_MAX_VOLUME : title_volume);
  317.  
  318.   modify_sound(background_channel, period2[note_count],
  319.     title_volume > TITLE_MAX_VOLUME? TITLE_MAX_VOLUME : title_volume);
  320.  
  321.   if(++note_count >= 9)
  322.     note_count = 8;
  323. }
  324.  
  325.  
  326.  
  327. load_waveforms()
  328. {
  329.   register int i, incomplete;
  330.   static char *notall[] =
  331.   {
  332.     "Not all of the sound effects",
  333.     "could be loaded.  If you wish",
  334.     "to hear all possible sounds,",
  335.     "quit this program, free up some",
  336.     "memory (by closing existing",
  337.     "programs or deleting files from",
  338.     "RAM), then run this program again."
  339.   };
  340.   static char *none[] =
  341.   {
  342.     "NONE of the sound effects",
  343.     "could be loaded.  Make sure",
  344.     "that the \"samples\" directory",
  345.     "exists on the same disk as",
  346.     "Advanced Laser Chess and rerun",
  347.     "the program if you wish to",
  348.     "hear all of the sound effects."
  349.   };
  350.  
  351.   /* The order in which the waveforms are loaded denote their priority.
  352.   That is, the first waveform loaded (considered the most important)
  353.   has the best chance of successfully "making it" into memory.  The
  354.   succeeding waveforms have a lower chance of successfully loading
  355.   because of the continuous memory decline. */
  356.  
  357.   waveform[WAVE_BACKGROUND] = load_raw_sample(BACKGROUND_FILENAME,
  358.     &wavelength[WAVE_BACKGROUND]);
  359.  
  360.   waveform[WAVE_BEEP0] = load_raw_sample(BEEP0_FILENAME,
  361.     &wavelength[WAVE_BEEP0]);
  362.  
  363.   waveform[WAVE_BEEP1] = load_raw_sample(BEEP1_FILENAME,
  364.     &wavelength[WAVE_BEEP1]);
  365.  
  366.   waveform[WAVE_LASER] = load_raw_sample(LASER_FILENAME,
  367.     &wavelength[WAVE_LASER]);
  368.  
  369.   waveform[WAVE_CRUNCH] = load_raw_sample(CRUNCH_FILENAME,
  370.     &wavelength[WAVE_CRUNCH]);
  371.  
  372.   waveform[WAVE_EXPLODE] = load_raw_sample(EXPLODE_FILENAME,
  373.     &wavelength[WAVE_EXPLODE]);
  374.  
  375.   waveform[WAVE_VICTORY] = load_raw_sample(VICTORY_FILENAME,
  376.     &wavelength[WAVE_VICTORY]);
  377.  
  378.   waveform[WAVE_TITLE] = load_raw_sample(TITLE_FILENAME,
  379.     &wavelength[WAVE_TITLE]);
  380.  
  381.   waveform[WAVE_HYPERIN] = load_raw_sample(HYPERIN_FILENAME,
  382.     &wavelength[WAVE_HYPERIN]);
  383.  
  384.   waveform[WAVE_HYPEROUT] = load_raw_sample(HYPEROUT_FILENAME,
  385.     &wavelength[WAVE_HYPEROUT]);
  386.  
  387.   waveform[WAVE_DISKOPEN] = load_raw_sample(DISKOPEN_FILENAME,
  388.     &wavelength[WAVE_DISKOPEN]);
  389.  
  390.   waveform[WAVE_DISKCLOSE] = load_raw_sample(DISKCLOSE_FILENAME,
  391.     &wavelength[WAVE_DISKCLOSE]);
  392.  
  393.   incomplete = TRUE;  /* Check to see if ANY waveforms got loaded */
  394.   for(i=0; i<NUMSAMPLES; i++)
  395.     if(waveform[i] != NULL)
  396.       incomplete = FALSE;
  397.   if(incomplete)  /* If none loaded, display message */
  398.     req(none, "Ok", "Ok", 7, FALSE);
  399.   else  /* Check to see if ALL of the waveforms have been loaded */
  400.   {
  401.     incomplete = FALSE;
  402.     for(i=0; i<NUMSAMPLES; i++)
  403.       if(waveform[i] == NULL)
  404.         incomplete = TRUE;
  405.     if(incomplete)  /* If not, display message */
  406.       req(notall, "Ok", "Ok", 7, FALSE);
  407.   }
  408. }
  409.  
  410.  
  411.  
  412. struct IOAudio *allocate_ioaudio(channel)
  413. register int channel;
  414. {
  415.   struct IOAudio *new;
  416.  
  417.   if(channel < 0 || channel > 3 || !in_use[channel]) return;
  418.  
  419.   new = allocate_mem((long)sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
  420.   if(new != NULL)
  421.   {
  422.     new->ioa_Request.io_Unit = unit[channel];
  423.     new->ioa_Request.io_Device = ioaudio->ioa_Request.io_Device;
  424.     new->ioa_Request.io_Message.mn_ReplyPort = dynamic_port;
  425.     new->ioa_AllocKey = allockey[channel];
  426.   }
  427.   return(new);
  428. }
  429.  
  430.  
  431.  
  432. /* Returns -1 if no channel available, otherwise 0 - 3. */
  433. allocate_audio_channel(priority)
  434. register int priority;
  435. {
  436.   static UBYTE audio_alloc[] = {1, 2, 8, 4}; /* Audio channel alloc. table */
  437.   int channel_alloc;
  438.  
  439.   ioaudio->ioa_Request.io_Command = ADCMD_ALLOCATE;
  440.   ioaudio->ioa_Request.io_Flags = ADIOF_NOWAIT;
  441.   ioaudio->ioa_Request.io_Unit = NULL;
  442.   ioaudio->ioa_AllocKey = 0;
  443.   ioaudio->ioa_Request.io_Message.mn_Node.ln_Pri = priority;
  444.   ioaudio->ioa_Data = audio_alloc;
  445.   ioaudio->ioa_Length = 4L;
  446.  
  447.   BeginIO(ioaudio);
  448.   if(ioaudio->ioa_Request.io_Error != NULL)
  449.     return(-1);
  450.  
  451.   switch((long)ioaudio->ioa_Request.io_Unit)
  452.   {
  453.     case 1L: channel_alloc = 0; break;
  454.     case 2L: channel_alloc = 1; break;
  455.     case 4L: channel_alloc = 2; break;
  456.     case 8L: channel_alloc = 3; break;
  457.     default: channel_alloc = -1; break;
  458.   }
  459.   if(channel_alloc != -1)
  460.   {
  461.     unit[channel_alloc] = ioaudio->ioa_Request.io_Unit;
  462.     allockey[channel_alloc] = ioaudio->ioa_AllocKey;
  463.     in_use[channel_alloc] = TRUE;
  464.   }
  465.  
  466.   return(channel_alloc);
  467. }
  468.  
  469.  
  470.  
  471. start_sound(channel, data, length, period, volume, cycles)
  472. int channel, period, volume, cycles;
  473. UBYTE *data;
  474. ULONG length;
  475. {
  476.   struct IOAudio *ioa;
  477.  
  478.   if(channel < 0 || channel > 3 || data == NULL || !in_use[channel])
  479.     return;
  480.   if((ioa = allocate_ioaudio(channel)) == NULL)
  481.     return;
  482.  
  483.   ioa->ioa_Request.io_Command = CMD_WRITE;
  484.   ioa->ioa_Request.io_Flags = ADIOF_PERVOL;
  485.   ioa->ioa_Data = data;
  486.   ioa->ioa_Length = length;
  487.   ioa->ioa_Period = (long)period;
  488.   ioa->ioa_Volume = (long)volume;
  489.   ioa->ioa_Cycles = (long)cycles;
  490.   clean_port();
  491.   BeginIO(ioa);
  492. }
  493.  
  494.  
  495.  
  496. modify_sound(channel, period, volume)
  497. register int channel, period, volume;
  498. {
  499.   struct IOAudio ioa;
  500.  
  501.   if(channel < 0 || channel > 3 || !in_use[channel])
  502.     return;
  503.  
  504.   /* QuickIO always succeeds for ADCMD_PERVOL, so I'll take advantage
  505.   of the advantage and USE it; an IOAudio structure will not have to
  506.   be dynamically allocated for each ADCMD_PERVOL for this reason. */
  507.   ioa.ioa_Request.io_Unit = unit[channel];
  508.   ioa.ioa_Request.io_Device = ioaudio->ioa_Request.io_Device;
  509.   ioa.ioa_Request.io_Message.mn_ReplyPort = static_port;
  510.   ioa.ioa_AllocKey = allockey[channel];
  511.   ioa.ioa_Request.io_Command = ADCMD_PERVOL;
  512.   ioa.ioa_Request.io_Flags = IOF_QUICK;
  513.   ioa.ioa_Period = (long)period;
  514.   ioa.ioa_Volume = (long)volume;
  515.   BeginIO(&ioa);
  516. }
  517.  
  518.  
  519.  
  520. end_sound(channel, sync)
  521. register int channel, sync;
  522. {
  523.   struct IOAudio *ioa;
  524.  
  525.   if(channel < 0 || channel > 3 || !in_use[channel]) return;
  526.   if((ioa = allocate_ioaudio(channel)) == NULL) return;
  527.  
  528.   ioa->ioa_Request.io_Command = ADCMD_FINISH;
  529.   ioa->ioa_Request.io_Flags = sync == NOW? 0L : ADIOF_SYNCCYCLE;
  530.   clean_port();
  531.   BeginIO(ioa);
  532. }
  533.  
  534.  
  535.  
  536. free_audio_channel(channel)
  537. register int channel;
  538. {
  539.   if(channel < 0 || channel > 3 || !in_use[channel]) return;
  540.  
  541.   in_use[channel] = FALSE;
  542.  
  543.   ioaudio->ioa_Request.io_Unit = unit[channel];
  544.   ioaudio->ioa_AllocKey = allockey[channel];
  545.   ioaudio->ioa_Request.io_Command = ADCMD_FREE;
  546.   ioaudio->ioa_Request.io_Flags = 0L;
  547.   BeginIO(ioaudio);
  548. }
  549.  
  550.  
  551.  
  552. free_waveforms()
  553. {
  554.   register int i;
  555.  
  556.   for(i=0; i<NUMSAMPLES; i++)
  557.     if(waveform[i] != NULL)
  558.       FreeMem(waveform[i], wavelength[i]);
  559. }
  560.  
  561.  
  562.  
  563. finish_channels() /* Performs an ADCMD_FINISH command for each channel... */
  564. {                 /* currently playing. */
  565.   register int i;
  566.  
  567.   for(i=0; i<4; i++)
  568.     free_audio_channel(i);
  569. }
  570.  
  571.  
  572.  
  573. clean_port()  /* Frees all dynamic IOAudio structures from dynamic_port */
  574. {
  575.   struct IOAudio *ioa;
  576.  
  577.   while((ioa = (struct IOAudio *)GetMsg(dynamic_port)) != NULL)
  578.     FreeMem(ioa, (long)sizeof(struct IOAudio));
  579. }
  580.  
  581.  
  582.  
  583. UBYTE *load_raw_sample(filename, length)
  584. char *filename;
  585. ULONG *length;
  586. {
  587.   FILE *file;
  588.   UBYTE *buffer;
  589.   ULONG size;
  590.   register ULONG i;
  591.  
  592.   if((file = fopen(filename, "r")) == NULL)
  593.     return(NULL);
  594.  
  595.   fseek(file, 0L, 2);  /* Seek to end of file */
  596.   size = ftell(file) & ~1L;  /* Size of file (in bytes) */
  597.   fseek(file, 0L, 0);  /* Seek to beginning of file */
  598.  
  599.   /* Allocate a buffer the same size as the file about to be read */
  600.   if((buffer = allocate_mem(size, MEMF_CHIP)) == NULL)
  601.   {
  602.     fclose(file);
  603.     return(NULL);
  604.   }
  605.  
  606.   /* NOTE: Files over 32K bytes cannot be handled using the following
  607.   fread() call as it stands; if bigger files need to be loaded, change
  608.   the fread() to load in longwords. */
  609.   *length = (ULONG)fread(buffer, 1, (int)size, file);
  610.  
  611.   fclose(file);
  612.  
  613.   return(buffer);
  614. }
  615.  
  616.  
  617.  
  618. close_sound()
  619. {
  620.   register int i;
  621.  
  622.   background_sound(FALSE, 0);
  623.   finish_channels();
  624.   if(dynamic_port != NULL)
  625.     clean_port();
  626.   if(clup & CLUP_AUDIODEV)
  627.     CloseDevice(ioaudio);
  628.   if(ioaudio != NULL)
  629.     FreeMem(ioaudio, (long)sizeof(struct IOAudio));
  630.   if(static_port != NULL)
  631.     DeletePort(static_port);
  632.   if(dynamic_port != NULL)
  633.     DeletePort(dynamic_port);
  634.   free_waveforms();
  635. }
  636.  
  637.  
  638.